home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Demo Folder / Swap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  4.9 KB  |  239 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Blob Manager Demonstration:  Coin Swap module
  3.  *
  4.  * This has a linear board with either 5, 7 or 9 pieces.  The middle
  5.  * piece is always empty, the pieces on one end are filled with black
  6.  * coins, the pieces on the other end are filled with white coins.
  7.  * The object is to swap the coins.  A coin can slide into an empty
  8.  * piece next to it, or jump over a single coin to land on an empty
  9.  * piece.
  10.  *
  11.  * A menu allows the number of coins to be chosen.  To win, the coins
  12.  * have to be swapped in a specific number of moves.
  13.  *
  14.  * 26 July 1986        Paul DuBois
  15.  */
  16.  
  17. # include    "TransSkel.h"
  18.  
  19. # include    "BlobMgr.h"
  20. # include    "BlobDemo.h"
  21.  
  22.  
  23. # define    vMessage    10
  24. # define    vPiece        30
  25. # define    maxPieces    9
  26. # define    pieceSize    24
  27. # define    pieceGap    1
  28.  
  29.  
  30. static WindowPtr        wind;
  31. static MenuHandle        cnfgMenu;
  32. static BlobSetHandle    donors = nil;
  33. static BlobSetHandle    receptors = nil;
  34. static short            hMid;
  35. static Str255            statusStr = "\p";
  36.  
  37. static short            nPieces = 5;
  38. static short            nMoves = 8;
  39. static BlobHandle        piece[maxPieces];
  40. static short            moves;
  41. static Boolean            pause;
  42.     
  43.  
  44. static void
  45. StatusMesg (StringPtr s)
  46. {
  47. Rect    r;
  48.  
  49.     SetRect (&r, hMid - 60, vMessage, hMid + 60, vMessage+16);
  50.     TextBox    (s+1, (long) s[0], &r, teJustCenter);
  51.     StrCpy (statusStr, s);
  52. }
  53.  
  54.  
  55. /*
  56.  * Reset to start state.  This recreates the board each time.  All the
  57.  * blobs in the board require explicit matches except the middle one.
  58.  */
  59.  
  60. static void
  61. Reset (void)
  62. {
  63. BlobHandle    b;
  64. Rect        r;
  65. short        i, h;
  66. Str255        s;
  67.  
  68.     InvalRect (&wind->portRect);    /* force update when done resetting */
  69.     pause = false;
  70.     moves = nMoves;
  71.     MovesLeft (moves, s);
  72.     StatusMesg (s);
  73.  
  74.     if (receptors != nil)                /* clobber any existing receptor set */
  75.     {
  76.         HideBlobSet (receptors);
  77.         DisposeBlobSet (receptors);
  78.     }
  79.     receptors = NewBlobSet ();
  80.  
  81.     h = hMid - (nPieces * (pieceSize + pieceGap) - pieceGap) / 2;
  82.     for (i = 0; i < nPieces; ++i)
  83.     {
  84.         b = NewBlob (receptors, true, 0, i != (nPieces - 1) / 2, 0L);
  85.         piece[i] = b;
  86.         OpenBlob ();
  87.         SetRect (&r, h, vPiece, h + pieceSize, vPiece + pieceSize);
  88.         EraseRect (&r);
  89.         FrameRect (&r);
  90.         CloseRectBlob (b, &r, &r);
  91.         h += pieceSize + pieceGap;
  92.         if (i < (nPieces - 1) / 2)
  93.         {
  94.             GlueGlob (GetBlobHandle (donors, 0), b);
  95.             NewBlobMatch (GetBlobHandle (donors, 1), b);
  96.         }
  97.         else if (i > (nPieces - 1) / 2)
  98.         {
  99.             GlueGlob (GetBlobHandle (donors, 1), b);
  100.             NewBlobMatch (GetBlobHandle (donors, 0), b);
  101.         }
  102.     }
  103. }
  104.  
  105.  
  106. static void
  107. SwapPause (StringPtr msg)
  108. {
  109.     StatusMesg (msg);
  110.     pause = true;
  111. }
  112.  
  113.  
  114. static pascal void
  115. Mouse (Point pt, long t, short mods)
  116. {
  117. Str255    s;
  118. short    i;
  119.  
  120.     /*
  121.      * Freeze all the pieces that can't be moved, then call BlobClick().
  122.      */
  123.     for (i = 0; i < nPieces; ++i)
  124.     {
  125.         ThawBlob (piece[i]);
  126.         if (BGlob (piece[i]) == nil) continue;
  127.         if (i > 0 && BGlob (piece[i-1]) == nil) continue;
  128.         if (i > 1 && BGlob (piece[i-2]) == nil) continue;
  129.         if (i < nPieces - 1 && BGlob (piece[i+1]) == nil) continue;
  130.         if (i < nPieces - 2 && BGlob (piece[i+2]) == nil) continue;
  131.         FreezeBlob (piece[i]);
  132.     }
  133.     if (!pause)
  134.     {
  135.         BlobClick (pt, t, donors, receptors);
  136.         if (BClickResult () == bcXfer)
  137.         {
  138.             if (--moves == 0)
  139.             {
  140.                 if (BlobSetQuiet (receptors))
  141.                     SwapPause ("\pYou Win");
  142.                 else
  143.                     SwapPause ("\pYou Lose");
  144.             }
  145.             else
  146.             {
  147.                 MovesLeft (moves, s);
  148.                 StatusMesg (s);
  149.             }
  150.         }
  151.     }
  152. }
  153.  
  154.  
  155. static pascal void
  156. Update (Boolean resized)
  157. {
  158.     DrawBlobSet (receptors);
  159.     StatusMesg (statusStr);
  160. }
  161.  
  162.  
  163. /*
  164.  * Select configuration:  4, 6, or 8 coins (2, 3, or 4 on each side).
  165.  * If the number of coins on each side is n, the number of moves
  166.  * to solve is (n+1)^2 - 1.
  167.  */
  168.  
  169. static pascal void
  170. DoConfiguration (short item)
  171. {
  172.     nPieces = 2 * item + 3;            /* 1->5, 2->7, 3->9 pieces */
  173.     nMoves = (item + 2) * (item + 2) - 1;
  174.     Reset ();
  175. }
  176.  
  177.  
  178. static pascal void
  179. Activate (Boolean active)
  180. {
  181.     if (active)
  182.     {
  183.         SetDragRects (wind);
  184.         SetBCPermissions (false, true, false, false, false);    /* xfer only */
  185.         cnfgMenu = GetMenu (swapCnfgMenuRes);
  186.         SkelMenu (cnfgMenu, DoConfiguration, DoMClobber, false, true);
  187.     }
  188.     else
  189.         SkelRmveMenu (cnfgMenu);
  190. }
  191.  
  192.  
  193. static void
  194. MakeDonors (void)
  195. {
  196. BlobHandle    b;
  197. Rect        r;
  198.  
  199.     donors = NewBlobSet ();
  200.     b = NewBlob (donors, true, infiniteGlue, false, 0L);
  201.     OpenBlob ();
  202.     SetRect (&r, 0, 0, pieceSize, pieceSize);
  203.     EraseRect (&r);
  204.     FrameRect (&r);
  205.     InsetRect (&r, 2, 2);
  206.     PaintOval (&r);
  207.     InsetRect (&r, -2, -2);
  208.     CloseRectBlob (b, &r, &r);
  209.     b = NewBlob (donors, true, infiniteGlue, false, 0L);
  210.     OpenBlob ();
  211.     PaintRect (&r);
  212.     InsetRect (&r, 2, 2);
  213.     EraseOval (&r);
  214.     InsetRect (&r, -2, -2);
  215.     CloseRectBlob (b, &r, &r);
  216. }
  217.  
  218.  
  219. void
  220. SwapInit (void)
  221. {
  222.     SkelWindow (wind = GetDemoWind (swapWindRes),
  223.                 Mouse,            /* mouse clicks */
  224.                 nil,            /* key clicks */
  225.                 Update,            /* updates */
  226.                 Activate,        /* activate/deactivate events */
  227.                 nil,            /* close window */
  228.                 DoWClobber,        /* dispose of window */
  229.                 nil,            /* idle proc */
  230.                 false);            /* irrelevant, since no idle proc */
  231.  
  232.     hMid = wind->portRect.right / 2;
  233.  
  234.     MakeDonors ();
  235.     Reset ();
  236.  
  237.     MakeFrontWind (wind);
  238. }
  239.